using System.Xml;
using System.Xml.Serialization;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
using Core.Graphics.Tiles;

namespace Core.Graphics
{
    [XmlRoot("TileSet")]
    public class TileSet
    {
        [XmlAttribute("TileSetID")]
        public int ID { get { return _ID; } set { _ID = value; } }
        /// <summary>Get TileSet Name</summary>
        [XmlAttribute("Name")]
        public string Name { get { return _Name; } set { _Name = value; } }
        /// <summary>Get Vertical Spacing between each Tile in Pixels</summary>
        [XmlAttribute("VerticalSpacing")]
        public int VerticalSpacing { get { return _VerticalSpacing; } set { _VerticalSpacing = value; } }
        /// <summary>Get Horizontal Spacing between each Tile in Pixels</summary>
        [XmlAttribute("HorizontalSpacing")]
        public int HorizontalSpacing { get { return _HorizontalSpacing; } set { _HorizontalSpacing = value; } }
        /// <summary>Get Tile Width in Pixels</summary>
        [XmlAttribute("TileWidth")]
        public int TileWidth { get { return _TileWidth; } set { _TileWidth = value; } }
        /// <summary>Get Tile Height in Pixels</summary>
        [XmlAttribute("TileHeight")]
        public int TileHeight { get { return _TileHeight; } set { _TileHeight = value; } }
        /// <summary>Get # Of Tiles Per Row</summary>
        [XmlAttribute("TilesPerRow")]
        public int TilesPerRow { get { return _TilesPerRow; } set { _TilesPerRow = value; } }
        /// <summary>Get # of Tiles Per Column</summary>
        [XmlAttribute("TilesPerColumn")]
        public int TilesPerColumn { get { return _TilesPerColumn; } set { _TilesPerColumn = value; } }
        /// <summary>Get TileSet's Last Tile ID</summary>
        [XmlAttribute("TileCount")]
        public int TileCount { get { return _TileCount; } set { _TileCount = value; } }
        [XmlIgnore()]
        public TileSetTileCollection Tiles { get { return _Tiles; } set { _Tiles = value; } }
        [XmlIgnore()]
        public Texture2D TileSetTexture { get { return _TileSetTexture; } set { _TileSetTexture = value; } }
        [XmlArray("Texture")]
        public uint[] TextureAsUInt
        {
            get
            {
                if (_TextureAsUInt != null)
                    return _TextureAsUInt;

                uint[] data = new uint[_TileSetTexture.Width * _TileSetTexture.Height];

                _TileSetTexture.GetData<uint>(data);

                return data;
            }

            set
            {
                //When Deserializing object we will have to convert this to a texture again.
                _TextureAsUInt = value;
            }
        }

        protected uint[] _TextureAsUInt;

        protected int _ID;
        protected string _Name;
        protected int _VerticalSpacing;
        protected int _HorizontalSpacing;
        protected int _TileWidth;
        protected int _TileHeight;
        protected int _TilesPerRow;
        protected int _TilesPerColumn;
        protected int _TileCount;
        protected TileSetTileCollection _Tiles;

        protected Texture2D _TileSetTexture;

        public TileSet(int ID, Texture2D texture, string name, int tilewidth, int tileheight, int horizontalspacing, int verticalspacing)
        {
            _ID = ID;
            _Name = name;
            _HorizontalSpacing = horizontalspacing;
            _VerticalSpacing = verticalspacing;
            _TileWidth = tilewidth;
            _TileHeight = tileheight;
            _TileSetTexture = texture;

            _Tiles = new TileSetTileCollection();

            _TilesPerRow = _TileSetTexture.Width / _TileWidth;
            _TilesPerColumn = _TileSetTexture.Height / _TileHeight;
            _TileCount = _TilesPerColumn * _TilesPerRow;

            //Load Tiles From TileSet Texture
            LoadTilesFromSet();
        }

        public TileSet()
        {
            //For XML Serialization
        }

        public void AfterLoadFromFileProcedure(GraphicsDevice device)
        {
            //Recreate Texture
            _TileSetTexture = new Texture2D(device, _TilesPerRow * _TileWidth, _TilesPerColumn * _TileHeight,
                1, TextureUsage.None, SurfaceFormat.Color);
            //Load Texture data
            _TileSetTexture.SetData<uint>(_TextureAsUInt);
            //Instantiate other objects
            _Tiles = new TileSetTileCollection();

            LoadTilesFromSet();
        }

        private void LoadTilesFromSet()
        {
            for (int i = 0; i < _TileCount; i++)
            {
                TileSetTile mt = new TileSetTile(i, this);

                _Tiles.Add(mt);
            }
        }

        public override string ToString()
        {
            return Name;
        }
    }
}
